﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImagePro
{
    public enum TransformType
    {
        UD, LR, Center, Shun, Ni
    }

    public enum ResizeMode
    {
        Fill, Contain, Cover
    }

    class ImageHelper
    {
        public ImageHelper(Bitmap bitmap)
        {
            Bitmap = bitmap;
        }

        public Bitmap Bitmap { get; }

        //private Bitmap grayImage;
        //public Bitmap GrayImage
        //{
        //    get
        //    {
        //        if (grayImage == null)
        //        {
        //            return GetGray();
        //        }
        //        else
        //        {
        //            return grayImage;
        //        }
        //    }
        //}

        public Bitmap GetGray()
        {
            ImageAttributes imageAttributes = new ImageAttributes();
            float[][] matrix = { new float[] {0.299f, 0.299f, 0.299f, 0, 0},
                                             new float[]   {0.587f,   0.587f,   0.587f,   0,   0},
                                             new float[]   {0.114f,   0.114f,   0.114f,   0,   0},
                                             new float[]   {0,   0,   0,   1,   0},
                                             new float[]   {0,   0,   0,   0,   1}
                                   };
            ColorMatrix colorMatrix = new ColorMatrix(matrix);
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            Bitmap gray = new Bitmap(Bitmap.Width, Bitmap.Height);
            using (Graphics g = Graphics.FromImage(gray))
            {
                g.DrawImage(Bitmap, new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), 0, 0, Bitmap.Width, Bitmap.Height, GraphicsUnit.Pixel, imageAttributes);
            }
            //grayImage = grayHead;
            return gray;
        }

        public Bitmap GetAnti()
        {
            ImageAttributes imageAttributes = new ImageAttributes();
            float[][] matrix = {
                new float[] {-1, 0, 0, 0, 0},
                new float[] {0, -1, 0, 0, 0},
                new float[] {0, 0, -1, 0, 0 },
                new float[] {0, 0, 0, 1, 0},
                new float[] {1, 1, 1, 0, 1} };
            ColorMatrix colorMatrix = new ColorMatrix(matrix);
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            Bitmap anti = new Bitmap(Bitmap.Width, Bitmap.Height);
            using (Graphics g = Graphics.FromImage(anti))
            {
                g.DrawImage(Bitmap, new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), 0, 0, Bitmap.Width, Bitmap.Height, GraphicsUnit.Pixel, imageAttributes);
            }
            return anti;
        }

        public Bitmap GetMainColor(Dictionary<Color, Color> colorss, ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = (Bitmap)Bitmap.Clone();
            List<Color> colorKeys = colorss.Keys.ToList();
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    Color c = r.GetPixel(x, y);
                    int minIndex = 0, minVal = ColorClustering.ColorSub(colorKeys[0], c);
                    for (int i = 1; i < colorKeys.Count; i++)
                    {
                        int p = ColorClustering.ColorSub(colorKeys[i], c);
                        if (p < minVal)
                        {
                            minIndex = i;
                            minVal = p;
                        }
                    }
                    r.SetPixel(x, y, colorss[colorKeys[minIndex]]);
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetVal2(ColorClustering.Progress Pro)
        {
            Pro(0);
            Bitmap r = (Bitmap)Bitmap.Clone();
            for (int y = 0; y < r.Height; y++)
            {
                Pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    Color sc = r.GetPixel(x, y);
                    r.SetPixel(x, y, sc.R + sc.G + sc.B > 383 ? Color.White : Color.Black);
                }
            }
            Pro(100);
            return r;
        }

        public Bitmap GetFilter(Color color, bool single = false)
        {
            Bitmap r = new Bitmap(Bitmap.Width, Bitmap.Height);
            ImageAttributes imageAttributes = new ImageAttributes();
            float[][] matrix = {
                new float[] {color.R / 255.0f, 0, 0, 0, 0},
                new float[] {0, color.G / 255.0f, 0, 0, 0},
                new float[] {0, 0, color.B / 255.0f, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1} };
            ColorMatrix colorMatrix = new ColorMatrix(matrix);
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            using (Graphics g = Graphics.FromImage(r))
            {
                if (single)
                {
                    g.DrawImage(GetGray(), new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), 0, 0, Bitmap.Width, Bitmap.Height, GraphicsUnit.Pixel, imageAttributes);
                }
                else
                {
                    g.DrawImage(Bitmap, new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), 0, 0, Bitmap.Width, Bitmap.Height, GraphicsUnit.Pixel, imageAttributes);
                }
            }
            return r;
        }

        public Bitmap GetTransformUD(ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = new Bitmap(Bitmap.Width, Bitmap.Height);
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    r.SetPixel(x, r.Height - y - 1, Bitmap.GetPixel(x, y));
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetTransformLR(ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = new Bitmap(Bitmap.Width, Bitmap.Height);
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    r.SetPixel(r.Width - x - 1, y, Bitmap.GetPixel(x, y));
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetTransformCenter(ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = new Bitmap(Bitmap.Width, Bitmap.Height);
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    r.SetPixel(x, y, Bitmap.GetPixel(Bitmap.Width - x - 1, Bitmap.Height - y - 1));
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetTransformClockwise(ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = new Bitmap(Bitmap.Height, Bitmap.Width);
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    r.SetPixel(x, y, Bitmap.GetPixel(y, Bitmap.Height - x - 1));
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetTransformCounterclockwise(ColorClustering.Progress pro)
        {
            pro(0);
            Bitmap r = new Bitmap(Bitmap.Height, Bitmap.Width);
            for (int y = 0; y < r.Height; y++)
            {
                pro(100 * y / r.Height);
                for (int x = 0; x < r.Width; x++)
                {
                    r.SetPixel(x, y, Bitmap.GetPixel(Bitmap.Width - y - 1, x));
                }
            }
            pro(100);
            return r;
        }

        public Bitmap GetTransformResize(Size size, ResizeMode resizeMode = ResizeMode.Fill)
        {
            Bitmap r = new Bitmap(size.Width, size.Height);
            using (Graphics g = Graphics.FromImage(r))
            {
                switch (resizeMode)
                {
                    case ResizeMode.Fill:
                        g.DrawImage(Bitmap, 0, 0, size.Width, size.Height);
                        break;
                    case ResizeMode.Contain:
                        if (Bitmap.Width / Bitmap.Height > size.Width / size.Height)
                        {
                            int h = Bitmap.Height * size.Width / Bitmap.Width;
                            g.DrawImage(Bitmap, 0, (size.Height - h) / 2, size.Width, h);
                        }
                        else
                        {
                            int w = Bitmap.Width * size.Height / Bitmap.Height;
                            g.DrawImage(Bitmap, (size.Width - w) / 2, 0, w, size.Height);
                        }
                        break;
                    case ResizeMode.Cover:
                        if (Bitmap.Width / Bitmap.Height > size.Width / size.Height)
                        {
                            int w = Bitmap.Width * size.Height / Bitmap.Height;
                            g.DrawImage(Bitmap, (size.Width - w) / 2, 0, w, size.Height);
                        }
                        else
                        {
                            int h = Bitmap.Height * size.Width / Bitmap.Width;
                            g.DrawImage(Bitmap, 0, (size.Height - h) / 2, size.Width, h);
                        }
                        break;
                    default:
                        break;
                }

            }
            return r;
        }

        public Bitmap GetTransform(TransformType transformType, ColorClustering.Progress pro)
        {
            switch (transformType)
            {
                case TransformType.UD:
                    return GetTransformUD(pro);
                case TransformType.LR:
                    return GetTransformLR(pro);
                case TransformType.Center:
                    return GetTransformCenter(pro);
                case TransformType.Shun:
                    return GetTransformClockwise(pro);
                case TransformType.Ni:
                    return GetTransformCounterclockwise(pro);
                default:
                    return Bitmap;
            }
        }
    }
}
